/*
This file is part of Arcadeflex.

Arcadeflex is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Arcadeflex is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Arcadeflex.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * ported to v0.28
 * ported to v0.27
 *
 *
 *
 */
package vidhrdw;

import static arcadeflex.osdepend.*;
import static arcadeflex.libc.*;
import static mame.common.*;
import static mame.commonH.*;
import static mame.driverH.*;
import static mame.mame.*;
import static mame.osdependH.*;
import static vidhrdw.generic.*;
import static machine.williams.*;
import static m6809.M6809.*;

public class williams {
    
         static final int START_OFFSET = 4;
         static final int VIDEO_RAM_SIZE = 0x9800;
         static int Erase_screen_each_vbl;     
         static char[] williams_videoram;
         static osd_bitmap williams_bitmap;
         static  char inverse_colors[]=new char[256];

        static char BlasterRemapProm[] = {
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x04,0x01,0x03,0x09,0x0A,0x01,0x0C,0x0D,0x0F,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x0C,0x0D,0x0A,0x09,0x0A,0x0C,0x0C,0x0D,0x0B,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x0C,0x0F,0x01,0x01,0x09,0x0A,0x07,0x0C,0x0D,0x06,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x01,0x09,0x0E,0x09,0x09,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x04,0x0C,0x0D,0x05,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x0C,0x09,0x0E,0x09,0x09,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x09,0x09,0x0E,0x01,0x0A,0x09,0x0C,0x0D,0x09,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x0C,0x0A,0x09,0x0C,0x0D,0x0B,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x05,0x0B,0x0E,0x0C,0x0B,0x06,0x0E,0x0D,0x07,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x05,0x06,0x0E,0x0C,0x06,0x01,0x0E,0x0D,0x03,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x05,0x01,0x0E,0x0C,0x01,0x0B,0x0E,0x0D,0x0D,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x05,0x0B,0x0E,0x0C,0x0B,0x0C,0x0E,0x0D,0x0D,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x04,0x0A,0x05,0x0C,0x0D,0x01,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x05,0x0C,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x05,0x01,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x06,0x03,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x0C,0x0B,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x0E,0x01,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x0E,0x0B,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x01,0x0B,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x0E,0x01,0x04,0x03,0x09,0x0B,0x0C,0x0C,0x0D,0x0B,0x0F,
             0x00,0x0F,0x02,0x0D,0x0C,0x0B,0x0A,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,
             0x00,0x03,0x02,0x07,0x09,0x0B,0x0D,0x0F,0x05,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x01,
             0x00,0x03,0x02,0x0E,0x07,0x01,0x0F,0x09,0x0D,0x06,0x08,0x0A,0x0C,0x05,0x04,0x0B,
             0x00,0x0B,0x02,0x05,0x0C,0x0A,0x04,0x06,0x0D,0x09,0x0F,0x01,0x07,0x0E,0x08,0x03,
             0x00,0x06,0x02,0x0A,0x0C,0x05,0x04,0x0B,0x03,0x08,0x0E,0x07,0x01,0x0F,0x09,0x0D,
             0x00,0x07,0x02,0x0D,0x0F,0x0C,0x04,0x0B,0x05,0x0A,0x06,0x09,0x01,0x03,0x08,0x0E,
             0x00,0x09,0x02,0x05,0x03,0x07,0x01,0x0D,0x0A,0x04,0x08,0x0F,0x06,0x0C,0x0B,0x0E,
             0x00,0x01,0x02,0x01,0x01,0x01,0x01,0x01,0x05,0x09,0x0C,0x01,0x0C,0x01,0x01,0x05,
             0x00,0x05,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x0C,0x01,0x0C,0x01,0x01,0x05,
             0x00,0x05,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x09,0x0C,0x01,0x0C,0x01,0x01,0x01,
             0x00,0x01,0x02,0x05,0x05,0x01,0x01,0x01,0x01,0x09,0x0C,0x01,0x0C,0x01,0x01,0x01,
             0x00,0x01,0x02,0x01,0x05,0x05,0x01,0x01,0x01,0x09,0x0C,0x01,0x0C,0x01,0x01,0x01,
             0x00,0x01,0x05,0x01,0x01,0x05,0x05,0x01,0x01,0x09,0x05,0x05,0x05,0x05,0x05,0x01,
             0x00,0x01,0x05,0x01,0x01,0x01,0x05,0x05,0x01,0x09,0x05,0x05,0x05,0x05,0x05,0x01,
             0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x05,0x05,0x09,0x05,0x05,0x05,0x05,0x05,0x01,
             0x00,0x00,0x02,0x03,0x0D,0x05,0x00,0x07,0x08,0x0D,0x00,0x0B,0x0C,0x0D,0x0D,0x0F,
             0x00,0x00,0x02,0x03,0x0D,0x05,0x09,0x07,0x08,0x09,0x00,0x0B,0x0C,0x0D,0x0D,0x0F,
             0x00,0x00,0x02,0x03,0x0D,0x05,0x00,0x07,0x08,0x0D,0x09,0x0B,0x0C,0x0D,0x09,0x0F,
             0x00,0x09,0x02,0x03,0x09,0x05,0x00,0x07,0x08,0x0D,0x00,0x0B,0x0C,0x0D,0x0D,0x0F,
             0x00,0x00,0x02,0x03,0x0D,0x05,0x00,0x07,0x08,0x0D,0x00,0x09,0x0C,0x0D,0x0D,0x0F,
             0x00,0x00,0x02,0x03,0x0D,0x05,0x09,0x07,0x08,0x09,0x00,0x09,0x0C,0x0D,0x0D,0x0F,
             0x00,0x00,0x02,0x03,0x0D,0x05,0x00,0x07,0x08,0x0D,0x09,0x09,0x0C,0x0D,0x09,0x0F,
             0x00,0x09,0x02,0x03,0x09,0x05,0x00,0x07,0x08,0x0D,0x00,0x09,0x0C,0x0D,0x0D,0x0F,
             0x00,0x0D,0x02,0x03,0x01,0x04,0x05,0x04,0x01,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x03,
             0x00,0x03,0x02,0x0D,0x03,0x01,0x04,0x05,0x04,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x01,
             0x00,0x01,0x02,0x03,0x0D,0x03,0x01,0x04,0x05,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x04,
             0x00,0x04,0x02,0x01,0x03,0x0D,0x03,0x01,0x04,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x05,
             0x00,0x05,0x02,0x04,0x01,0x03,0x0D,0x03,0x01,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x04,
             0x00,0x04,0x02,0x05,0x04,0x01,0x03,0x0D,0x03,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x01,
             0x00,0x01,0x02,0x04,0x05,0x04,0x01,0x03,0x0D,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x03,
             0x00,0x03,0x02,0x01,0x04,0x05,0x04,0x01,0x03,0x09,0x0E,0x0B,0x0C,0x0A,0x09,0x0D,
             0x00,0x0B,0x02,0x03,0x04,0x01,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x09,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x0C,0x02,0x03,0x04,0x01,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x05,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x05,0x02,0x0A,0x05,0x05,0x08,0x08,0x08,0x09,0x0A,0x0B,0x06,0x07,0x0E,0x06,
             0x00,0x09,0x02,0x0B,0x09,0x05,0x02,0x02,0x02,0x09,0x0A,0x0B,0x09,0x0A,0x0E,0x0E,
             0x00,0x04,0x02,0x03,0x01,0x05,0x05,0x05,0x05,0x09,0x0A,0x0B,0x04,0x03,0x0E,0x0F,
             0x00,0x01,0x02,0x0D,0x01,0x05,0x0B,0x0B,0x0B,0x09,0x0A,0x0B,0x05,0x01,0x0E,0x06,
             0x00,0x01,0x02,0x03,0x01,0x05,0x09,0x09,0x09,0x09,0x0A,0x0B,0x0F,0x01,0x0E,0x09,
             0x00,0x01,0x02,0x0D,0x01,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x05,0x04,0x0E,0x0F,
             0x00,0x02,0x02,0x03,0x04,0x05,0x0B,0x02,0x0B,0x09,0x0A,0x0B,0x0C,0x0D,0x02,0x0B,
             0x00,0x02,0x02,0x03,0x04,0x05,0x0B,0x02,0x09,0x09,0x0A,0x0B,0x0C,0x0D,0x09,0x0B,
             0x00,0x02,0x02,0x03,0x04,0x05,0x0B,0x09,0x0B,0x09,0x0A,0x0B,0x0C,0x0D,0x02,0x09,
             0x00,0x09,0x02,0x03,0x04,0x05,0x09,0x02,0x0B,0x09,0x0A,0x0B,0x0C,0x0D,0x02,0x0B,
             0x00,0x0E,0x02,0x0A,0x0B,0x09,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x0B,0x02,0x0A,0x01,0x09,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0C,0x0E,0x0F,
             0x00,0x07,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x04,0x0E,0x0F,
             0x00,0x01,0x02,0x0B,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0C,
             0x00,0x05,0x02,0x07,0x03,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x08,0x0E,0x09,
             0x00,0x0F,0x02,0x01,0x0C,0x0B,0x06,0x07,0x08,0x0D,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x08,0x02,0x06,0x07,0x09,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0A,0x0E,0x05,
             0x00,0x0C,0x02,0x08,0x03,0x04,0x0E,0x0E,0x0E,0x06,0x08,0x0B,0x0C,0x08,0x07,0x0F,
             0x00,0x0B,0x02,0x0A,0x0D,0x0C,0x0E,0x0E,0x0A,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0C,
             0x00,0x06,0x02,0x0D,0x02,0x0A,0x06,0x07,0x08,0x0C,0x01,0x0B,0x0C,0x0D,0x0F,0x0F,
             0x00,0x05,0x02,0x03,0x01,0x04,0x05,0x04,0x01,0x0F,0x03,0x0B,0x0C,0x0D,0x0A,0x0F,
             0x00,0x01,0x02,0x02,0x08,0x06,0x05,0x04,0x01,0x05,0x07,0x0B,0x0C,0x0D,0x0A,0x06,
             0x00,0x01,0x02,0x03,0x04,0x05,0x05,0x01,0x0E,0x09,0x01,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x05,0x06,0x0E,0x09,0x06,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x01,0x0E,0x09,0x01,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x0B,0x0E,0x09,0x0B,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x0E,0x0F,0x0C,0x0D,0x05,0x05,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x09,0x05,0x04,0x03,0x0C,0x0C,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x0F,0x04,0x01,0x03,0x06,0x06,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x09,0x0E,0x0A,0x0D,0x01,0x01,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x0A,0x02,0x0D,0x0C,0x0E,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x07,0x02,0x08,0x06,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x0C,0x02,0x03,0x04,0x06,0x0E,0x07,0x08,0x05,0x0A,0x0B,0x01,0x03,0x06,0x04,
             0x00,0x0C,0x02,0x03,0x04,0x06,0x02,0x07,0x08,0x05,0x0A,0x0B,0x01,0x03,0x06,0x04,
             0x00,0x05,0x02,0x0A,0x05,0x05,0x01,0x01,0x01,0x09,0x0A,0x0B,0x06,0x07,0x0E,0x06,
             0x00,0x05,0x02,0x0A,0x05,0x05,0x05,0x05,0x05,0x09,0x0A,0x0B,0x06,0x07,0x0E,0x06,
             0x00,0x01,0x02,0x03,0x04,0x05,0x02,0x02,0x02,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x09,0x02,0x0B,0x09,0x05,0x01,0x01,0x01,0x09,0x0A,0x0B,0x09,0x0A,0x0E,0x0E,
             0x00,0x04,0x02,0x03,0x01,0x05,0x01,0x01,0x01,0x09,0x0A,0x0B,0x04,0x03,0x0E,0x0F,
             0x00,0x02,0x02,0x03,0x04,0x05,0x01,0x02,0x01,0x02,0x0E,0x01,0x0C,0x01,0x02,0x01,
             0x00,0x02,0x02,0x03,0x04,0x05,0x01,0x02,0x05,0x02,0x0E,0x01,0x0C,0x01,0x05,0x01,
             0x00,0x02,0x02,0x03,0x04,0x05,0x01,0x05,0x01,0x02,0x0E,0x01,0x0C,0x01,0x02,0x05,
             0x00,0x05,0x02,0x03,0x04,0x05,0x05,0x02,0x01,0x02,0x0E,0x01,0x0C,0x01,0x02,0x01,
             0x00,0x02,0x02,0x0A,0x09,0x0E,0x0C,0x02,0x0C,0x02,0x0A,0x0C,0x0C,0x0A,0x02,0x0C,
             0x00,0x02,0x02,0x0A,0x09,0x0E,0x0C,0x02,0x0F,0x02,0x0A,0x0C,0x0C,0x0A,0x0F,0x0C,
             0x00,0x02,0x02,0x0A,0x09,0x0E,0x0C,0x09,0x0C,0x02,0x0A,0x0C,0x0C,0x0A,0x02,0x0F,
             0x00,0x09,0x02,0x0A,0x09,0x0E,0x0F,0x02,0x0C,0x02,0x0A,0x0C,0x0C,0x0A,0x02,0x0C,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x0B,0x0A,0x09,0x0C,0x0D,0x0B,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x03,0x04,0x05,0x0C,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x0B,0x09,0x0E,0x09,0x09,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x0C,0x09,0x0E,0x09,0x09,0x0B,0x0E,0x0D,0x0E,0x0F,
             0x00,0x01,0x02,0x03,0x04,0x05,0x01,0x04,0x03,0x09,0x0A,0x0B,0x04,0x03,0x0E,0x05,
             0x00,0x01,0x02,0x03,0x04,0x0E,0x06,0x07,0x08,0x09,0x0A,0x0B,0x04,0x03,0x0E,0x05,
             0x00,0x01,0x02,0x03,0x04,0x0E,0x05,0x04,0x03,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0A,
             0x00,0x01,0x02,0x03,0x04,0x06,0x05,0x04,0x03,0x0E,0x0A,0x0B,0x01,0x0D,0x0E,0x04,
             0x00,0x01,0x02,0x03,0x04,0x0C,0x01,0x01,0x03,0x09,0x0E,0x0B,0x07,0x08,0x0E,0x06,
             0x00,0x01,0x02,0x03,0x04,0x05,0x09,0x09,0x0A,0x09,0x0A,0x0B,0x01,0x0D,0x0E,0x0C,
             0x00,0x01,0x02,0x03,0x04,0x09,0x05,0x05,0x03,0x09,0x0A,0x0B,0x04,0x04,0x0E,0x03,
             0x00,0x01,0x02,0x03,0x04,0x01,0x0C,0x0C,0x0D,0x01,0x0D,0x0B,0x0A,0x0D,0x0E,0x09,
             0x00,0x01,0x02,0x03,0x04,0x0E,0x06,0x07,0x08,0x0E,0x0A,0x0B,0x04,0x04,0x0E,0x03,
             0x00,0x01,0x02,0x03,0x04,0x0F,0x04,0x01,0x03,0x0F,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        };
        static int TOTAL_COLORS(int gfxn) 
        {
            return Machine.gfx[gfxn].total_colors * Machine.gfx[gfxn].color_granularity;
        }
        public static VhConvertColorPromPtr williams_vh_convert_color_prom = new VhConvertColorPromPtr() { public void handler(char []palette_table, char []colortable_table, char []color_prom_table)
	{
                int i;
                CharPtr color_prom = new CharPtr(color_prom_table);
                CharPtr palette= new CharPtr(palette_table);
                /* the palette will be initialized by the game. We just set it to some */
                /* pre-cooked values so the startup copyright notice can be displayed. */
                for (i = 0;i < Machine.drv.total_colors;i++)
                {
                         palette.writeinc(((i & 1) >> 0) * 0xff);
                         palette.writeinc(((i & 2) >> 1) * 0xff);
                         palette.writeinc(((i & 4) >> 2) * 0xff);
                }

                /* initialize the color table */
                /* we reserve pen 0 for the background black which makes the */
                /* MS-DOS version look better */
                for (i = 0;i < TOTAL_COLORS(0);i++)
                        colortable_table[Machine.drv.gfxdecodeinfo[0].color_codes_start + i] = (char)( i + 1);
        }};

        /**************
         * Put 2 Pixels in the real bitmap
         */
         static final void PutPix2(int x,int y,int p1,int p2)
        {
               /* unsigned char *p = &williams_bitmap->line[x][y];
                unsigned char *lookup = Machine->gfx[0]->colortable;
                p[0] = lookup[p1];
                p[1] = lookup[p2];*/
                CharPtr p = new CharPtr(williams_bitmap.line[x],y);
                CharPtr lookup=new CharPtr(Machine.gfx[0].colortable,0);
                p.write(0,lookup.read(p1));
                p.write(1,lookup.read(p2));
        }


        /**************
         *
         */
      public static WriteHandlerPtr williams_videoram_w = new WriteHandlerPtr()
      {
        public void handler(int offset,int data)
        {
                int x,y;

                /* Put the byte in the videoram */
                williams_videoram[offset] = (char)data;

                /* Put the pixels in our bitmap */
                x = offset % 256;
        
                x -= START_OFFSET;
                if (x<0)
                  return;
                if (x>=240)
                  return;
        
                y = offset / 256;
                PutPix2(x, (y*2),   data>>4, data & 0x0F);
        }};

        /**************
         *
         */
       public static WriteHandlerPtr blaster_videoram_w = new WriteHandlerPtr()
       {
         public void handler(int offset,int data)
         {
                int x,y;


        /*Put the byte in the videoram*/
                RAM[offset] = (char)data;

        /*Put the pixels in our bitmap*/
                x = offset % 256;
        
                x -= START_OFFSET;
                if(x<0)
                        return;
                if(x>=240)
                        return;
       
                y = offset / 256;
                PutPix2(x,(y*2),data>>4,data&0x0F);

        }};

        /**************
         *
         */
       public static ReadHandlerPtr williams_videoram_r = new ReadHandlerPtr()
       {
          public int handler(int offset) {

                /* Read the video ram or the ROM */
                if(RAM[0xc900] == 0){
                    if(offset>>8 >= 0x98)
                           return RAM[offset];
                    else
                           return williams_videoram[offset];
                }else
                    return RAM[offset];
        }};


        /**************
         *
         */
       public static ReadHandlerPtr blaster_videoram_r = new ReadHandlerPtr()
       {
          public int handler(int offset) {


                if(offset>>8 < 0x40)
                        if(RAM[0xc900] == 0){
                                return RAM[offset];
                }else{
                        return RAM[bank_address+offset];
                }


        /*   Read the video ram or the ROM
         */

         if(RAM[0xc900] == 0){
                 return RAM[offset];
         }else
          if(offset>>8 >= 0x97)
                 return RAM[offset];
          else
                 return RAM[0x40000+offset];
        }};




        /**************
         * Write in the video ram for the blitter
         */
        static void williams_videoram_blitter_w(int offset,int data,int flag,int p1,int p2,char[] vram)
        {
            	int x,y;
	int pb1,pb2;
	CharPtr bm=new CharPtr();

	/*  Calcul the real x-y	 */
	x = offset % 256;
	y = offset / 256;


	x -= START_OFFSET;
	if (x<0 || x>=240)
		return;


        /*
         1000 0000 Do not process half the byte 4-7
         0100 0000 Do not process half the byte 0-3
         0010 0000 Shift the shape one pixel right (to display a shape on an odd pixel)
         0001 0000 Remap, if shape != 0 then = mask
         0000 1000 Source  1 = take source 0 = take Mask only
         0000 0100
         0000 0010 Transparent
         0000 0001
        */

        /*  Background pixels
         */
	/*  Background pixels  */
	bm.set(williams_bitmap.line[x],((y * 2) + ((flag >> 5) & 1)));
	pb1 = inverse_colors[bm.read(0)];
	pb2 = inverse_colors[bm.read(1)];
        
	/*  Not optimized yet, there must be a way to do that faster  */
	if ((flag & 0x08) == 0)
	{
		if ((flag & 0x10) == 0)
		{
			if ((flag & 0x80) == 0)
				pb1 = p1;
			if((flag & 0x40) == 0)
				pb2 = p2;
		}
		else
		{
			if ((flag & 0x80) == 0)
				pb1 = RAM[0xCA01] >> 4;
			if ((flag & 0x40) == 0)
				pb2 = RAM[0xCA01] & 0x0F;
		}
	}
	else
	{
		if ((flag & 0x10) == 0)
		{
			if (p1 != 0)
				if ((flag & 0x80) == 0)
					pb1 = p1;
			if (p2 != 0)
				if ((flag & 0x40) == 0)
					pb2 = p2;
		}
		else
		{
			if (p1 != 0)
				if ((flag & 0x80) == 0)
					pb1 = RAM[0xCA01] >> 4;
			if (p2 != 0)
				if ((flag & 0x40) == 0)
					pb2 = RAM[0xCA01] & 0x0f;
		}

	}


/*   Clip if outside the video then it is in RAM[]
 *   Bubble blit some code at $9800 +
 */

	if (offset >= 0x9800)
	{

/*   But do not write on ROM, Joust blit at $FXXX when a shape pass the
 *   left of the screen
 */

		if (offset >= 0xE000)
			return;
		RAM[offset] = (char)data;
		return;
	}

/*  Put the byte in the videoram
 *  Not really good if flag & 0x20 != 0
 *  But the games seem to never read the video ram.
 */
	vram[offset] = (char)((pb1 << 4) + pb2);

	/*  Put the pixels in our bitmap  */
	bm.write(0,Machine.gfx[0].colortable.read(pb1));
	bm.write(1,Machine.gfx[0].colortable.read(pb2));

        }


        static final int SCREEN_WIDTH = 256;


        /**************
         *
         */
        public static WriteHandlerPtr williams_StartBlitter = new WriteHandlerPtr()
        {
            public void handler(int offset,int data)
            {

        int i,j,offs;
        int source,dest,start;

          offs = SCREEN_WIDTH - RAM[0xCA07];
          source = (RAM[0xCA02]<<8) + RAM[0xCA03];
          start = (RAM[0xCA04]<<8) + RAM[0xCA05];
          dest = start;

	if((RAM[0xCA06]^4) == 0)
	{

/*  Special case for Bubbles , will work correctly when my blitter routine
 *  will check the transparent flag
 *  Blit some code from rom to ram.
 */

		for(i=0;i<=(RAM[0xCA07]^4);i++)
		{
			for(j=0;j<=(RAM[0xCA06]^4);j++)
			{
				int pix = RAM[source];
				int p1 = pix >> 4;
				int p2 = pix & 0x0F;
				williams_videoram_blitter_w(dest,pix,data,p1,p2,williams_videoram);
				source=(char)(source+1);//sign extend
                                dest=(char)(dest+SCREEN_WIDTH);//sign extend
			}
			start =(char)(start+1);//sign extend
                        dest = start;
		}
	}
	else
	{
		for(i=0;i<(RAM[0xCA07]^4);i++)
		{
			for(j=0;j<(RAM[0xCA06]^4);j++)
			{
				int pix = williams_videoram_r.handler(source);
				int p1 = pix >> 4;
				int p2 = pix & 0x0F;
				williams_videoram_blitter_w(dest,pix,data,p1,p2,williams_videoram);
				source=(char)(source+1);//sign extend
                                dest=(char)(dest+SCREEN_WIDTH);//sign extend
			}
			start =(char)(start+1);//sign extend
            dest = start;
		}
	}

        /*  Log blits
         */
              if (errorlog != null)
              {
                fprintf(errorlog, "---------- Blit %02X--------------PC: %04X\n", new Object[] { Integer.valueOf(data), Integer.valueOf(m6809_GetPC()) });
                fprintf(errorlog, "Source : %02X %02X\n", new Object[] { Character.valueOf(RAM[0xCA02]), Character.valueOf(RAM[0xCA03]) });
                fprintf(errorlog, "Dest   : %02X %02X\n", new Object[] { Character.valueOf(RAM[0xCA04]), Character.valueOf(RAM[0xCA05]) });
                fprintf(errorlog, "W H    : %02X %02X (%d,%d)\n", new Object[] { Character.valueOf(RAM[0xCA06]), Character.valueOf(RAM[0xCA07]), Integer.valueOf(RAM[0xCA06]^4), Integer.valueOf(RAM[0xCA07]^4) });
                fprintf(errorlog, "Mask   : %02X\n", new Object[] { Character.valueOf(RAM[0xCA01]) });
              }

        }};


        /**************
         * Same as StartBlitter but call williams_videoram_blaster_blitter_w
         * instead of williams_videoram_blitter_w to remap with the Remap Prom
         */
        public static WriteHandlerPtr williams_BlasterStartBlitter = new WriteHandlerPtr()
        {
            public void handler(int offset,int data)
            {
        int i,j,offs;
        int source,dest,start;

          offs = SCREEN_WIDTH - RAM[0xCA07];
          source = (RAM[0xCA02]<<8) + RAM[0xCA03];
          start = (RAM[0xCA04]<<8) + RAM[0xCA05];
          dest = start;

          CharPtr remap=new CharPtr(BlasterRemapProm,RAM[0xc940] * 16);

            for(i=0;i<RAM[0xCA07];i++){
                for(j=0;j<RAM[0xCA06];j++){
                  int pix = blaster_videoram_r.handler(source);
                            int p1 = pix >> 4;
                            int p2 = pix & 0x0F;
                  williams_videoram_blitter_w(dest,pix,data,remap.read(p1),remap.read(p2),RAM);
                  source=(char)(source+1);//sign extend
                    dest=(char)(dest+SCREEN_WIDTH);//sign extend
                }
                start =(char)(start+1);//sign extend
            dest = start;
              }
            

        /*  Log blits
         */
              if (errorlog != null)
              {
                fprintf(errorlog, "---------- Blit %02X--------------PC: %04X\n", new Object[] { Integer.valueOf(data), Integer.valueOf(m6809_GetPC()) });
                fprintf(errorlog, "Source : %02X %02X\n", new Object[] { Character.valueOf(RAM[0xCA02]), Character.valueOf(RAM[0xCA03]) });
                fprintf(errorlog, "Dest   : %02X %02X\n", new Object[] { Character.valueOf(RAM[0xCA04]), Character.valueOf(RAM[0xCA05]) });
                fprintf(errorlog, "W H    : %02X %02X (%d,%d)\n", new Object[] { Character.valueOf(RAM[0xCA06]), Character.valueOf(RAM[0xCA07]), Integer.valueOf(RAM[0xCA06]^4), Integer.valueOf(RAM[0xCA07]^4) });
                fprintf(errorlog, "Mask   : %02X\n", new Object[] { Character.valueOf(RAM[0xCA01]) });
              }

        }};

        /**************
         * Same as StartBlitter but no ^ 4 with the Width and Length
         * For Splat or any game that use SC2 ships.
         */
        public static WriteHandlerPtr williams_StartBlitter2 = new WriteHandlerPtr()
        {
            public void handler(int offset,int data)
            {
        int i,j,offs;
        int source,dest,start;

          offs = SCREEN_WIDTH - RAM[0xCA07];
          source = (RAM[0xCA02]<<8) + RAM[0xCA03];
          start = (RAM[0xCA04]<<8) + RAM[0xCA05];
          dest = start;

           for(i=0;i<(RAM[0xCA07]);i++){
            for(j=0;j<(RAM[0xCA06]);j++){
              int pix = williams_videoram_r.handler(source);
                        int p1 = pix >> 4;
                        int p2 = pix & 0x0F;
              williams_videoram_blitter_w(dest,pix,data,p1,p2,williams_videoram);
              source=(char)(source+1);//sign extend
              dest=(char)(dest+SCREEN_WIDTH);//sign extend
            }
            start =(char)(start+1);//sign extend
            dest = start;
          }
           
        /*  Log blits
         */
              if (errorlog != null)
              {
                fprintf(errorlog, "---------- Blit %02X--------------PC: %04X\n", new Object[] { Integer.valueOf(data), Integer.valueOf(m6809_GetPC()) });
                fprintf(errorlog, "Source : %02X %02X\n", new Object[] { Character.valueOf(RAM[0xCA02]), Character.valueOf(RAM[0xCA03]) });
                fprintf(errorlog, "Dest   : %02X %02X\n", new Object[] { Character.valueOf(RAM[0xCA04]), Character.valueOf(RAM[0xCA05]) });
                fprintf(errorlog, "W H    : %02X %02X (%d,%d)\n", new Object[] { Character.valueOf(RAM[0xCA06]), Character.valueOf(RAM[0xCA07]), Integer.valueOf(RAM[0xCA06]), Integer.valueOf(RAM[0xCA07]) });
                fprintf(errorlog, "Mask   : %02X\n", new Object[] { Character.valueOf(RAM[0xCA01]) });
              }
        }};

        public static WriteHandlerPtr Williams_Palette_w = new WriteHandlerPtr()
        {
            public void handler(int offset,int data)
            {

              	int r, g, b;

	int bit0,bit1,bit2;


        RAM[offset+0xC000] = (char)data;


	/* red component */
	bit0 = (data >> 0) & 0x01;
	bit1 = (data >> 1) & 0x01;
	bit2 = (data >> 2) & 0x01;
	r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
	/* green component */
	bit0 = (data >> 3) & 0x01;
	bit1 = (data >> 4) & 0x01;
	bit2 = (data >> 5) & 0x01;
	g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
	/* blue component */
	bit0 = 0;
	bit1 = (data >> 6) & 0x01;
	bit2 = (data >> 7) & 0x01;
	b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;

	osd_modify_pen (Machine.gfx[0].colortable.read(offset), r, g, b);
            }
        };


        /********************* Defender ******************************/


        /**************
         * Defender video ram Write
         * Same as the others but Write in RAM[]
         */
        public static WriteHandlerPtr defender_videoram_w = new WriteHandlerPtr()
        {
            public void handler(int offset,int data)
            {
                int x,y;

                /*  defender only!!
                 */

                  RAM[offset] = (char)data;

                /*  Put the pixels in our bitmap
                 */

                  x = offset % 256;
                
                  x -= START_OFFSET;
                  if(x<0)
                    return;
                  if(x>=240)
                    return;
                
                  y = offset / 256;

                  PutPix2(x,(y*2),data>>4,data&0x0F);

              }
        };






        /***************************************************************************
          Start the video hardware emulation.
        ***************************************************************************/
	public static VhStartPtr williams_vh_start = new VhStartPtr() { public int handler()
	{
                if ((tmpbitmap = osd_create_bitmap(Machine.drv.screen_width,Machine.drv.screen_height)) == null)
                        return 1;

                /*  Allocate space for video ram  */
                if ((williams_videoram = new char[VIDEO_RAM_SIZE]) == null)
                {
                        osd_free_bitmap(tmpbitmap);
                        tmpbitmap=null;
                        return 1;
                }
                memset(williams_videoram,0,VIDEO_RAM_SIZE);

                defender_bank = 0;
                Erase_screen_each_vbl = 0;

                williams_bitmap = tmpbitmap;

                	/* generate the inverse colors table */
                memset (inverse_colors, 0, sizeof (inverse_colors));
                for (int i = 0; i < 16; i++)
                        inverse_colors[Machine.gfx[0].colortable.read(i)] = (char)i;
        
                return 0;
        }};

        /***************************************************************************

          Stop the video hardware emulation.

        ***************************************************************************/
        public static VhStopPtr williams_vh_stop = new VhStopPtr() { public void handler()
	{
                williams_videoram=null;
                osd_free_bitmap(tmpbitmap);
                tmpbitmap=null;
        }};
        

        /***************************************************************************

          Draw the game screen in the given osd_bitmap.
          Do NOT call osd_update_display() from this function, it will be called by
          the main emulation engine.

        ***************************************************************************/
        public static VhUpdatePtr williams_vh_screenrefresh = new VhUpdatePtr() { public void handler(osd_bitmap bitmap)
	{

            copybitmap(bitmap,williams_bitmap,0,0,0,0,Machine.drv.visible_area,TRANSPARENCY_NONE,0);

        }};

        public static VhUpdatePtr blaster_vh_screenrefresh = new VhUpdatePtr() { public void handler(osd_bitmap bitmap)
	{  

	williams_vh_screenrefresh.handler(bitmap);

	/* Toggle the erase video ram each frames (for Blaster) */

	if (osd_key_pressed(OSD_KEY_EQUALS))
	{
		Erase_screen_each_vbl ^= 1;
		while (osd_key_pressed(OSD_KEY_EQUALS));	/* wait for key release */
	}

	/* Semi automatic erase video ram each frames (for Blaster) */

	if (Erase_screen_each_vbl != 0)
            for (int k = 20; k < 240; k++)
                memset(williams.williams_bitmap.line[k], 0, 304);
       

        }};   
}
